package cn.ug.pay.web.job;

import cn.ug.bean.base.DataTable;
import cn.ug.bean.base.Page;
import cn.ug.config.RedisGlobalLock;
import cn.ug.pay.bean.MemberGoldBean;
import cn.ug.pay.bean.ProductOrderBean;
import cn.ug.pay.bean.type.ProductOrderPayStatus;
import cn.ug.pay.bean.type.ProductOrderStatus;
import cn.ug.pay.mapper.entity.PayAccountRecord;
import cn.ug.pay.mapper.entity.PayFundsRecord;
import cn.ug.pay.mapper.entity.PayTbillStatistics;
import cn.ug.pay.service.*;
import cn.ug.util.PaginationUtil;
import cn.ug.util.UF;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.List;
import java.util.concurrent.TimeUnit;

/**
 * 会员资产定时任务
 * @author kaiwotech
 */
@Component
public class MemberGoldJobs {
    private Log log = LogFactory.getLog(MemberGoldJobs.class);
    /** 业务有效期 */
    private static final long EXPIRE_DAY = 1024;
    @Resource
    private ProductOrderService productOrderService;
    @Autowired
    private PayAccountRecordService payAccountRecordService;
    @Resource
    private MemberGoldService memberGoldService;
    @Resource
    private RedisGlobalLock redisGlobalLock;
    @Autowired
    private PayFundsRecordService payFundsRecordService;
    @Autowired
    private PayTbillStatisticsService payTbillStatisticsService;
    /**
     * 定期转活期（定期产品收益发放）
     */
    @Scheduled(cron = "0 0 1,2,3 * * ?")
    //@Scheduled(cron = "0 56 11 * * ?")
    public void productOrderIncomeJob() {
        SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH");
        String key = "MemberGoldJobs:expiredProductOrderJob:" + format.format(Calendar.getInstance().getTime());
        if(!redisGlobalLock.lock(key, EXPIRE_DAY, TimeUnit.DAYS)) {
            // 如果没有获取到锁
            return;
        }
        log.info("定期转活期 开始");
        log.info(UF.getFormatDateTime(UF.getDateTime()));
        do {
            List<ProductOrderBean> dataTable = productOrderService.queryBecomeDueOrders();
            if(null == dataTable || dataTable.size()  == 0) {
                log.info("定期转活期 结束");
                return;
            }

            for (ProductOrderBean o : dataTable) {
                String productOrderKey = "MemberGoldJobs:expiredProductOrderJob:" + o.getId() + format.format(Calendar.getInstance().getTime());
                try {
                    if(!redisGlobalLock.lock(productOrderKey, EXPIRE_DAY, TimeUnit.DAYS)) {
                        continue;
                    }
                    // 定期转活期
                    productOrderService.completeProductOrder(o.getId());
                } catch (Exception e) {
                    // 释放锁
                    log.error("定期转活期出错。memberId：" + o.getMemberId() + ", memberMobile:" + o.getMemberMobile(), e);
                    redisGlobalLock.unlock(productOrderKey);
                }
            }
            try {
                Thread.sleep(5000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        } while (true);
    }

    /**
     * 活期产品每日利息计算发放（每10秒触发一次，每天执行一次）
     * 2018-12-17 提单版本第一版上线后，柚子钱包不在产生收益
     */
    //@Scheduled(cron = "0/10 1 0 * * ?")
    public void interestCalculateJob() {
        String key = "MemberGoldJobs:interestCalculateJob:" + UF.getFormatDateNow();
        if(!redisGlobalLock.lock(key, EXPIRE_DAY, TimeUnit.DAYS)) {
            // 如果没有获取到锁
            return;
        }
        log.info("每日利息计算发放 开始");
        log.info(UF.getFormatDateTime(UF.getDateTime()));

        Page page = new Page();
        page.setPageSize(1000);
        page.setPageNum(1);
        do {
            List<MemberGoldBean> dataTable = memberGoldService.queryActiveAccountForCurrentList(PaginationUtil.getOffset(page.getPageNum(), page.getPageSize()), PaginationUtil.getPageSize(page.getPageSize()));

            if(null == dataTable || dataTable.size() == 0) {
                log.info("每日利息计算发放 结束");
                return;
            }

            for (MemberGoldBean o : dataTable) {
                String memberKey = key + ":" + o.getMemberId();
                try {
                    if(!redisGlobalLock.lock(memberKey, EXPIRE_DAY, TimeUnit.DAYS)) {
                        continue;
                    }

                    // 发放并计算当日收益
                    memberGoldService.interestCalculate(o.getMemberId());
                } catch (Exception e) {
                    // 释放锁
                    log.error("发放并计算当日收益出错。memberId：" + o.getMemberId() + ", memberMobile:" + o.getMemberMobile(), e);
                    redisGlobalLock.unlock(memberKey);
                }
            }

            // 下一页
            page.setPageNum(page.getPageNum() + 1);
        } while (true);
    }

    @Scheduled(cron = "0/10 40 23 * * ?")
    //@Scheduled(cron = "0/10 29 15 * * ?")
    public void generateMemberAccountRecordJob() {
        String key = "MemberGoldJobs:generateMemberAccountRecordJob:" + UF.getFormatDateNow();
        if(!redisGlobalLock.lock(key, EXPIRE_DAY, TimeUnit.DAYS)) {
            // 如果没有获取到锁
            return;
        }
        log.info("产生会员资产账户记录 开始");

        Page page = new Page();
        page.setPageSize(1000);
        page.setPageNum(1);
        do {
            List<MemberGoldBean> dataTable = memberGoldService.queryActiveAccountForList(PaginationUtil.getOffset(page.getPageNum(), page.getPageSize()), PaginationUtil.getPageSize(page.getPageSize()));

            if(null == dataTable || dataTable.size() == 0) {
                log.info("产生会员资产账户记录 结束");
                return;
            }
            List<PayAccountRecord> records = new ArrayList<PayAccountRecord>();
            try {
                for (MemberGoldBean o : dataTable) {
                    PayAccountRecord record = new PayAccountRecord();
                    record.setAddDate(UF.getFormatDateNow());
                    record.setCurrentInterestGram(o.getInterestAmount());
                    record.setCurrentPrincipalGram(o.getPrincipalAmount());
                    record.setMemberId(o.getMemberId());
                    record.setRegularInterestGram(o.getFreezeIncomeAmount());
                    record.setRegularPrincipalGram(o.getFreezeBuyAmount());
                    record.setTotalGram(o.getTotalAmount());
                    records.add(record);
                }
            } catch (Exception e) {
                continue;
            }
            payAccountRecordService.save(records);
            page.setPageNum(page.getPageNum() + 1);
        } while (true);
    }

    @Scheduled(cron = "0/10 45 23 * * ?")
    //@Scheduled(cron = "0/10 11 17 * * ?")
    public void generateMemberFundsRecordJob() {
        String key = "MemberGoldJobs:generateMemberFundsRecordJob:" + UF.getFormatDateNow();
        if(!redisGlobalLock.lock(key, EXPIRE_DAY, TimeUnit.DAYS)) {
            // 如果没有获取到锁
            return;
        }
        log.info("产生会员资金账户记录 开始");

        Page page = new Page();
        page.setPageSize(1000);
        page.setPageNum(1);
        do {
            List<PayFundsRecord> dataTable = payFundsRecordService.queryActiveAccountForList(PaginationUtil.getOffset(page.getPageNum(), page.getPageSize()), PaginationUtil.getPageSize(page.getPageSize()));

            if(null == dataTable || dataTable.size() == 0) {
                log.info("产生会员资金账户记录 结束");
                return;
            }
            try {
                payFundsRecordService.save(dataTable);
            } catch (Exception e) {
                continue;
            }
            page.setPageNum(page.getPageNum() + 1);
        } while (true);
    }

    /**
     * 每日可用资产详表记录（每10秒触发一次，每天执行一次）
     */
    @Scheduled(cron = "0/10 30 23 * * ?")
    public void recordGoldDetailPerDay() {
        String key = "MemberGoldJobs:recordGoldDetailPerDay:" + UF.getFormatDateNow();
        if(!redisGlobalLock.lock(key, EXPIRE_DAY, TimeUnit.DAYS)) {
            // 如果没有获取到锁
            return;
        }
        log.info("每日可用资产详表记录 开始");
        log.info(UF.getFormatDateTime(UF.getDateTime()));

        Page page = new Page();
        page.setPageSize(1000);
        page.setPageNum(1);

        do {
            List<PayTbillStatistics> dataTable =  payTbillStatisticsService.query(-1, null, null, -1, -1, null, null, PaginationUtil.getOffset(page.getPageNum(), page.getPageSize()), PaginationUtil.getPageSize(page.getPageSize()));

            if(null == dataTable || dataTable.size() == 0) {
                log.info("每日可用资产详表记录 结束");
                return;
            }

            for (PayTbillStatistics o : dataTable) {
                String memberKey = key + ":" + o.getMemberId();
                try {
                    if(!redisGlobalLock.lock(memberKey, EXPIRE_DAY, TimeUnit.DAYS)) {
                        continue;
                    }

                    // 每日可用资产详表记录
                    memberGoldService.recordGoldDetailPerDay(o.getMemberId());
                } catch (Exception e) {
                    // 释放锁
                    redisGlobalLock.unlock(memberKey);
                }
            }

            // 下一页
            page.setPageNum(page.getPageNum() + 1);
        } while (true);
    }

}
